﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DirectionController : MonoBehaviour
{
    public GameObject body;

    class KeyData
    {
        KeyCode _code;
        public KeyCode code { get { return _code; }}

        Vector2 _dir;
        public Vector2 dir { get { return _dir; }}

        List<KeyCode> _conflicts = new List<KeyCode>();
        public List<KeyCode> conflicts { get { return _conflicts;}}

        public bool isDown;

        public KeyData(KeyCode code,Vector2 dir)
        {
            this.isDown = false;
            this._code = code;
            this._dir = dir;
        }

        public void AddConflict(KeyCode code)
        {
            _conflicts.Add(code);
        }
    }

    private Dictionary<KeyCode,KeyData> keys = new Dictionary<KeyCode,KeyData>();
    private Vector2 curDir = new Vector2(0,0);

    public Vector2 CurDir
    {
        get { return curDir; }
    }

    private bool needUpdate = false;
    private Vector3 srcPos;
    private Vector3 destPos;

    public bool enable = true;

    void Awake()
    {
        keys[KeyCode.W] = new KeyData(
            KeyCode.W,
            new Vector2(0,1)
        );
        keys[KeyCode.A] = new KeyData(
            KeyCode.A,
            new Vector2(-1,0)
        );
        keys[KeyCode.S] = new KeyData(
            KeyCode.S,
            new Vector2(0,-1)
        );
        keys[KeyCode.D] = new KeyData(
            KeyCode.D,
            new Vector2(1,0)
        );

        var conflicts1 = new List<KeyCode>();
        conflicts1.Add(KeyCode.W);
        conflicts1.Add(KeyCode.S);
        AddConflict(conflicts1);

        var conflicts2 = new List<KeyCode>();
        conflicts2.Add(KeyCode.A);
        conflicts2.Add(KeyCode.D);
        AddConflict(conflicts2);
    }

    private void AddConflict(List<KeyCode> list)
    {
        foreach(var key in list)
        {
            var keyData = keys[key];
            foreach(var v in list)
            {
                keyData.AddConflict(v);
            }
        }
    }

    private bool CanDown(KeyCode code)
    {
        foreach(var key in keys[code].conflicts)
        {
            if(keys[key].isDown)
            {
                return false;
            }
        }
        return true;
    }

    // Start is called before the first frame update
    void Start()
    {
        srcPos = gameObject.transform.localPosition;
        destPos = srcPos;
    }

    // Update is called once per frame
    void Update()
    {
        if(!enable)
        {
            return;
        }

        foreach (KeyCode key in keys.Keys)
        {
            if(Input.GetKeyDown(key))
            {
                OnKeyDir(key,true);
            }
            if(Input.GetKeyUp(key))
            {
                OnKeyDir(key,false);
            }
        }

        if(needUpdate)
        {
            needUpdate = false;
            UpdateBody();
        }
    }

    void OnKeyDir(KeyCode code,bool isDown)
    {
        //Debug.Log("OnKeyDir:"+code+" isDown:"+isDown);

        var keyData = keys[code];

        if(isDown)
        {
            if(!keyData.isDown && CanDown(code))
            {
                keyData.isDown = true;
                curDir += keyData.dir;
                needUpdate = true;
            }
        }
        else
        {
            if(keyData.isDown)
            {
                keyData.isDown = false;
                curDir -= keyData.dir;
                needUpdate = true;
            }
        }
    }

    void UpdateBody()
    {
        destPos.x = srcPos.x + curDir.x * 20;
        destPos.y = srcPos.y + curDir.y * 20;
        gameObject.transform.localPosition = destPos;

        Debug.Log("("+curDir.x+","+curDir.y+")");
    }
}
